/** \file Types.hpp Types for network stuff
 *  \author Adrian Schweizer
 *  \created  $Sa 19 Jan 10:27:40 pm CET 2008 schwadri@SchwadriLaptop.local$
 *  \modified $Sa 19 Jan 10:56:39 pm CET 2008 schwadri@SchwadriLaptop.local$
 */

#include "Address.hpp"

#include <string>

#ifdef _WIN32
  #include <process.h>
  #include <winsock2.h>
  #include <ws2tcpip.h>
#else
  #include <netdb.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
#endif

// Maximum length of a hostname
#define     HOST_NAME_MAX   256

namespace network {

const unsigned int   Address::ANY     =   INADDR_ANY;
const unsigned int   Address::NONE    =   INADDR_NONE;

/** \brief Convert an Url string to an Ip
*/
Address::ip_type UrlToIp(const std::string& hostname)
{
    hostent * phe = gethostbyname( hostname.c_str() );

    if ( phe == 0 || phe->h_addr_list[ 0 ] == 0 )
    {
        return Address::NONE;
    }

    unsigned int addr;

    memcpy( &addr, phe->h_addr_list[ 0 ], phe->h_length );

    return addr;
}

/** \brief Convert an Ip to an Url string
*/
std::string IpToUrl(Address::ip_type ip)
{
    std::string name;
    hostent* he = gethostbyaddr((char*)&ip,sizeof(unsigned int),AF_INET);
    name    =   he->h_name;
    return name;
}

/** \brief Retreive the local hosts Ip.
 *  This returns the Ip of the localhost. Which depending on whether or not the host is behind a NAT device
 *  may be a local or global Ip.
 */
Address::ip_type LocalHostIp()
{
    char name[HOST_NAME_MAX];
    if(gethostname(name,HOST_NAME_MAX)==-1)
        return Address::NONE;
    hostent * phe = gethostbyname( name );
    if ( phe == 0 || phe->h_addr_list[ 0 ] == 0 )
    {
        return Address::NONE;
    }

    unsigned int addr;

    memcpy( &addr, phe->h_addr_list[ 0 ], phe->h_length );

    return addr;
}

/** \brief Returns a string containing the localhost's name
*/
std::string LocalHostName()
{
    char name[HOST_NAME_MAX];
    if(gethostname(name,HOST_NAME_MAX)==-1)
        return "";
    return name;
}

bool operator==(const Address& a1, const Address& a2)
{
    return a1.Ip() == a2.Ip() && a1.Port() == a2.Port();
}

}